package divestoclimb.checklist;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import divestoclimb.checklist.data.Checklist;
import divestoclimb.checklist.data.Template;
import divestoclimb.checklist.storage.DbAdapter;
import divestoclimb.checklist.storage.XmlAdapter;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.CursorAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;
import android.widget.AdapterView.AdapterContextMenuInfo;

/**
 * This Activity displays a list of templates from the database and a category
 * picker. Accepts as arguments AbsListByCategory.CATEGORY, a
 * category to display; and TemplateList.KEY_ONCLICK_ACTION, an action to take
 * on selection of a template (either TemplateList.ACTION_EDIT or
 * TemplateList.ACTION_NEW_CHECKLIST).
 *  
 * @author Ben Roberts (divestoclimb@gmail.com)
 */
public class TemplateList extends AbsListByCategory {

	// The key used to store the action to take when a template is selected
	public static final String KEY_ONCLICK_ACTION="onclick_action";
	
	private static final int DIALOG_CONFIRM_DELETE = 1;

	// Edit the selected template
	public static final int ACTION_EDIT=1;
	// Create a new checklist using this template
	public static final int ACTION_NEW_CHECKLIST=2;
	
	private static final int RESULT_SAVE_TEMPLATE = 3;

	
	private int mAction;						// The action to take on selection
	private String mSort;						// The sort option for this view
	
	private long mSelectedItem;					// Used to track a selected item
												// from a context menu if we need
												// to wait for confirmation
	// These are used to save the results from other Activities as returned
	// to onActivityResult. We can't actually process them until onResume.
	private String mExportPath;
	private File mImportPath;
	// Used for template exports
	private FilePickerHelper mFilePickerHelper;

	@Override
	protected void onCreate(Bundle icicle) {
		super.onCreate(icicle);

		registerForContextMenu(getListView());
		
		mFilePickerHelper = new FilePickerHelper(this);
		
		// For now there's only one way to sort Templates
		mSort=DbAdapter.KEY_TEMPLATE_NAME;

		Bundle params = icicle != null? icicle: getIntent().getExtras();
		if(params != null) {
			mAction = params.getInt(KEY_ONCLICK_ACTION, ACTION_EDIT);
		} else {
			mAction = ACTION_EDIT;	// A safe default
		}
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		
		if(mExportPath != null) {
			// Export the template to the given location
			try {
				File path = new File(mExportPath);
				mExportPath = null;
				if(! path.getParentFile().isDirectory()) {
					path.getParentFile().mkdirs();
				}
				FileWriter buffer = new FileWriter(path);
				XmlAdapter xmlHelper = new XmlAdapter(getDbHelper());
				xmlHelper.writeTemplate(mSelectedItem, buffer);
				buffer.flush();
				buffer.close();
				Toast.makeText(this, R.string.template_saved, Toast.LENGTH_SHORT).show();
			} catch(IOException e) {
				String message;
				if(e instanceof FileNotFoundException) {
					message = getString(R.string.file_not_found);
				} else {
					message = getString(R.string.save_error);
				}
				Toast.makeText(this, String.format(message, e.getMessage()), Toast.LENGTH_LONG).show();
			}
		}
		
		if(mImportPath != null) {
			// Import a template from the given location
			FileReader buffer;
			try {
				buffer = new FileReader(mImportPath);
				XmlAdapter xmlHelper = new XmlAdapter(getDbHelper());
				xmlHelper.readTemplate(buffer, false);
				((CursorAdapter)getListView().getAdapter()).getCursor().requery();
			} catch (FileNotFoundException e) {
				Toast.makeText(this, String.format(getString(R.string.import_failed), e.getMessage()), Toast.LENGTH_LONG).show();
			}
		}
	}
	
	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		outState.putInt(KEY_ONCLICK_ACTION, mAction);
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		mImportPath = mFilePickerHelper.getFileFromResult(requestCode, resultCode, data);
		if(resultCode == RESULT_OK) {
			switch(requestCode) {
			case EditTemplate.ACTION_NEW:
				// Edit the new template
				Intent i = new Intent(this, EditTemplateItems.class);
				i.putExtra(DbAdapter.KEY_TEMPLATE_ID, data.getExtras().getLong(DbAdapter.KEY_TEMPLATE_ID));
				startActivityForResult(i, 0);
				break;
			case RESULT_SAVE_TEMPLATE:
				mExportPath = data.getExtras().getString(SaveDialog.PARAM_NAME);
			}
		}
	}
	
	/**
	 * Create a new Checklist based on a Template
	 * 
	 * @param template_id The database ID of the Template to use to make the Checklist
	 */
	protected void newChecklist(long template_id) {
		Checklist cl = getDbHelper().createChecklistFromTemplate(template_id);
		if(cl.getID() != -1) {
			Intent i = new Intent(this, FillChecklist.class);
			i.putExtra(DbAdapter.KEY_TEMPLATE_ID, cl.getID());
			startActivity(i);
		} else {
			// An error occurred creating the checklist. Odd...
		}
	}

	protected void deleteTemplate(long template_id) {
		getDbHelper().deleteTemplate(mSelectedItem);
		((CursorAdapter)getListView().getAdapter()).getCursor().requery();
	}
	
	// Interface event handlers/listeners

	@Override
	protected Dialog onCreateDialog(int id) {
		switch(id) {
		case DIALOG_CONFIRM_DELETE:
			return new AlertDialog.Builder(this)
			.setIcon(android.R.drawable.ic_dialog_alert)
			.setTitle(R.string.confirm_delete)
			.setMessage(R.string.confirm_template_delete)
			.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int whichButton) {
					deleteTemplate(mSelectedItem);
				}
			})
			.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int whichButton) {
					// Do nothing
				}
			})
			.create();
		}
		return null;
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.template_list, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch(item.getItemId()) {
		case R.id.new_template:
			long c = getCategoryId();
			Intent i = new Intent(this, EditTemplate.class)
				.putExtra("action", EditTemplate.ACTION_NEW)
				.putExtra(DbAdapter.KEY_TEMPLATE_CATEGORY, c >= 0? c: 0);
			startActivityForResult(i, EditTemplate.ACTION_NEW);
			break;
		case R.id.import_template:
			mFilePickerHelper.selectFile(D2cChecklist.TEMPLATE_DEFAULT_LOCATION,
					getString(R.string.choose_template), "", new String[] { D2cChecklist.TEMPLATE_EXTENSION });
			break;
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
		super.onCreateContextMenu(menu, v, menuInfo);
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.template_list_context, menu);
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
		Intent i;
		mSelectedItem = info.id;
		switch(item.getItemId()) {
		case R.id.edit:
			i = new Intent(this, EditTemplateItems.class);
			i.putExtra(DbAdapter.KEY_TEMPLATE_ID, info.id);
			startActivityForResult(i, 0);
			break;
		case R.id.new_checklist:
			newChecklist(info.id);
			break;
		case R.id.info:
			i = new Intent(this, EditTemplate.class)
				.putExtra("action", EditTemplate.ACTION_EDIT)
				.putExtra(DbAdapter.KEY_TEMPLATE_ID, info.id);

			startActivityForResult(i, 0);
			break;
		case R.id.delete:
			showDialog(DIALOG_CONFIRM_DELETE);
			break;
		case R.id.export:
			i = new Intent(this, SaveDialog.class);
			Template t = getDbHelper().fetchTemplate(info.id);
			i.putExtra(SaveDialog.PARAM_DEFAULT_NAME,
					t.getName()+"."+D2cChecklist.TEMPLATE_EXTENSION);
			i.putExtra(SaveDialog.PARAM_LOCATION, D2cChecklist.TEMPLATE_DEFAULT_LOCATION.getAbsolutePath());
			startActivityForResult(i, RESULT_SAVE_TEMPLATE);
		}
		
		return super.onContextItemSelected(item);
	}

	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		super.onListItemClick(l, v, position, id);
		if (position >= 0) {
			Cursor c = (Cursor) l.getItemAtPosition(position);
			long selected_template=c.getLong(c.getColumnIndexOrThrow(DbAdapter.KEY_TEMPLATE_ID));
			switch(mAction) {
			case ACTION_EDIT:
				Intent i = new Intent(this, EditTemplateItems.class);
				i.putExtra(DbAdapter.KEY_TEMPLATE_ID, selected_template);
				startActivityForResult(i, 0);
				break;
			case ACTION_NEW_CHECKLIST:
				newChecklist(selected_template);
				break;
			}
		}
	}

	@Override
	protected Cursor buildCursor() {
		long c = getCategoryId();
		return getDbHelper().fetchTemplates(mSort,
				c == SelectCategory.ID_ALL? -1: c);
	}

	@Override
	protected ListAdapter buildCursorAdapter(Cursor c) {
		return new SimpleCursorAdapter(this,
				android.R.layout.simple_list_item_1,
				c,
				new String[] { DbAdapter.KEY_TEMPLATE_NAME },
				new int[] { android.R.id.text1 });
	}

}